package com.mimo.common.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

public final class DateUtil {

  private DateUtil() {
    throw new UnsupportedOperationException();
  }

  /**
   * 获取某年第一天日期
   * 
   * @param year
   *          年份
   * @return Date
   */
  public static Date getYearFirst(int year) {
    Calendar calendar = Calendar.getInstance();
    calendar.clear();
    calendar.set(Calendar.YEAR, year);
    return calendar.getTime();
  }

  /**
   * 获取某年最后一天日期
   * 
   * @param year
   *          年份
   * @return Date
   */
  public static Date getYearLast(int year) {
    Calendar calendar = Calendar.getInstance();
    calendar.clear();
    calendar.set(Calendar.YEAR, year);
    calendar.roll(Calendar.DAY_OF_YEAR, -1);
    return calendar.getTime();
  }

  /**
   * 获取当年的第一天
   * 
   * @param year
   * @return
   */
  public static Date getCurrYearFirst() {
    Calendar currCal = Calendar.getInstance();
    int currentYear = currCal.get(Calendar.YEAR);
    return getYearFirst(currentYear);
  }

  /**
   * 获取当年的最后一天
   * 
   * @param year
   * @return
   */
  public static Date getCurrYearLast() {
    Calendar currCal = Calendar.getInstance();
    int currentYear = currCal.get(Calendar.YEAR);
    return getYearLast(currentYear);
  }

  public static Date parse(String pattern, String date) {
    try {
      return new SimpleDateFormat(pattern).parse(date);
    } catch (ParseException e) {
      throw new IllegalArgumentException(e);
    }
  }

  public static int getValueAsSeconds(Date date) {
    return (int) (date.getTime() / 1000);
  }

  public static int nowAsSeconds() {
    return (int) (System.currentTimeMillis() / 1000);
  }

  /**
   * 用于返回某个月份天数
   * 
   * @param year
   * @param month
   * @return
   */
  public static int getDaysOfMonth(int year, int month) {
    Calendar cal = Calendar.getInstance();
    cal.set(year, month - 1, 1);
    return getDaysOfMonth(cal.getTime());
  }

  public static int getDaysOfMonth(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
  }

  /**
   * 用于判断src是否落在 start 与 end 之间(开区间)
   *
   * @param src
   * @param start
   * @param end
   * @return
   */
  public static boolean isBetween(Date src, Date start, Date end) {
    return src.before(end) && src.after(start);
  }

  /**
   * 用于判断src是否落在 start 与 end 之间(双端闭区间)
   *
   * @param src
   * @param start
   * @param end
   * @return
   */
  public static boolean isBetweenWithBorderClose(Date src, Date start, Date end) {
    return src.compareTo(start) >= 0 && src.compareTo(end) <= 0;
  }

  /**
   * 用于判断src是否落在 start 与 end 之间(左闭右开)
   *
   * @param src
   * @param start
   * @param end
   * @return
   */
  public static boolean isBetweenLeftClosed(Date src, Date start, Date end) {
    return start.compareTo(src) <= 0 && src.before(end);
  }

  /**
   * 月份开头的时间 xx月01日 0：0：0
   *
   * @param date
   * @return
   */
  public static Date getMinDateOfMonth(Date date) {

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

    Calendar min = Calendar.getInstance();
    min.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.getActualMinimum(Calendar.DATE), 0, 0,
        0);

    return min.getTime();
  }

  /**
   * 获取当前日期的周一
   *
   * @param date
   * @return
   */
  public static Date getThisWeekMonday(Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    // 获得当前日期是一个星期的第几天
    int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
    if (1 == dayWeek) {
      cal.add(Calendar.DAY_OF_MONTH, -1);
    }
    // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
    cal.setFirstDayOfWeek(Calendar.MONDAY);
    // 获得当前日期是一个星期的第几天
    int day = cal.get(Calendar.DAY_OF_WEEK);
    // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
    cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
    return cal.getTime();
  }

  /**
   * 获取当前日期的周日
   *
   * @param date
   * @return
   */
  public static Date getThisWeekSunday(Date date) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);

    // 判断要计算的日期是否是周日，如果是则返回
    int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天  
    if (1 == dayWeek) {
      return date;
    }

    cal.add(Calendar.DATE, 8 - dayWeek);
    return cal.getTime();
  }

  /**
   * 月尾结束的时间 xx月31（30）日 23：59：59
   *
   * @param date
   * @return
   */
  public static Date getMaxDateOfMonth(Date date) {

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

    Calendar min = Calendar.getInstance();
    min.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.getActualMaximum(Calendar.DATE), 23, 59,
        59);

    return min.getTime();
  }

  /**
   * 用于计算得到特定日期的最大值。一般是23：59：59.
   *
   * @param date
   * @return
   */
  public static Date getMaxDateOfDay(Date date) {

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

    Calendar max = Calendar.getInstance();
    max.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 23, 59, 59);

    return max.getTime();

  }

  /**
   * @param date
   * @param field
   *          具体参考 {@link Calendar}中的静态字段
   * @param adjust
   * @return
   */
  public static Date addField(Date date, int field, int adjust) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(field, adjust);
    return calendar.getTime();
  }

  /**
   * 用于计算得到特定日期的最小值，一般为00:00:01.
   *
   * @param date
   * @return
   */
  public static Date getMinDateOfDay(Date date) {

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

    Calendar min = Calendar.getInstance();
    min.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 0, 0, 0);

    return min.getTime();
  }

  public static boolean isEqual(Date first, Date second) {
    return first.compareTo(second) == 0;
  }

  public static boolean isLessEqualThan(Date first, Date second) {
    return !first.after(second);
  }

  public static String format(String pattern, Date date) {
    Objects.requireNonNull(pattern);
    Objects.requireNonNull(date);

    return new SimpleDateFormat(pattern).format(date);
  }

  public static String format(String pattern, Date date, TimeZone zone) {
    Objects.requireNonNull(pattern);
    Objects.requireNonNull(date);
    Objects.requireNonNull(zone);

    SimpleDateFormat sdf = new SimpleDateFormat(pattern);
    sdf.setTimeZone(zone);
    return sdf.format(date);
  }

  /**
   * 秒数转化为指定格式的时间格式，如HH:mm:ss
   */
  public static String secendToDate(String pattern, Long second) {
    Objects.requireNonNull(pattern);
    Objects.requireNonNull(second);

    SimpleDateFormat formatter = new SimpleDateFormat(pattern);
    formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
    return formatter.format(TimeUnit.SECONDS.toMillis(second));
  }

  /**
   * 秒数转化为指定格式的时间格式，如HH:mm:ss
   */
  public static String secondsToCounterPattern(long elapsed) {
    int hour;
    int minute;
    int second;
    second = (int) (elapsed % 60);
    elapsed = elapsed / 60;
    minute = (int) (elapsed % 60);
    elapsed = elapsed / 60;
    hour = (int) elapsed;
    return String.format("%02d:%02d:%02d", hour, minute, second);
  }

  /**
   * 用于判断二个日期之间相关的天数
   *
   * @param fDate
   * @param oDate
   * @return
   */
  public static int getIntervalDays(Date fDate, Date oDate) {
    Objects.requireNonNull(fDate);
    Objects.requireNonNull(oDate);

    long intervalMilli = Math.abs(oDate.getTime() - fDate.getTime());

    return (int) (intervalMilli / (24 * 60 * 60 * 1000));

  }

  /**
   * 用于判断二个日期之间相差的毫秒数
   *
   * @param fDate
   * @param oDate
   * @return
   */
  public static long getIntervalMs(Date fDate, Date oDate) {
    Objects.requireNonNull(fDate);
    Objects.requireNonNull(oDate);
    return Math.abs(oDate.getTime() - fDate.getTime());
  }

  /**
   * 用于判断二个日期之间相差的秒数
   *
   * @param fDate
   * @param oDate
   * @return
   */
  public static long getIntervalSeconds(Date fDate, Date oDate) {
    Objects.requireNonNull(fDate);
    Objects.requireNonNull(oDate);
    return Math.abs(oDate.getTime() - fDate.getTime()) / 1000;
  }

  /**
   * 秒转时分 28800 -> 08:00
   * 
   * @param time
   * @return
   */
  public static String secondToTime(int time) {
    StringBuilder stringBuilder = new StringBuilder();
    Integer hour = time / 3600;
    Integer minute = time / 60 % 60;
    Integer second = time % 60;
    if (hour < 10) {
      stringBuilder.append("0");
    }
    stringBuilder.append(hour);
    stringBuilder.append(":");
    if (minute < 10) {
      stringBuilder.append("0");
    }
    stringBuilder.append(minute);
    stringBuilder.append(":");
    stringBuilder.append(second);

    return stringBuilder.toString();
  }

  /**
   * 时分转秒 08:00 -> 28800
   * 
   * @param time
   * @return
   */
  public static int timeToSecond(String time) {
    String[] str = time.split(":");
    Integer hour = Integer.valueOf(str[0]);
    Integer minute = Integer.valueOf(str[1]);
    Integer second = 0;
    second = second + hour * 3600;
    second = second + minute * 60;
    return second;
  }

}
